package com.atmc.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;


@Configuration
@EnableWebSecurity  // 开启WebSecurity模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService userDetailsService;
    @Autowired
    PersistentTokenRepository persistentTokenRepository;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //授权
        // 没有权限默认会到登录页面,需要开启登录的页面
        // /login页面
        // 开启自动配置的登录功能
        // /login 请求来到登录页
        // /login?error 重定向到这里表示登录失败
        http.formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                //自定义登录路径 去访问登录页
                .loginPage("/toLogin")
                //toSecurity 这个是由security 自动校验 用户及密码
                .loginProcessingUrl("/toSecurity")
                //校验成功后 的访问路径 指定要登录后访问的页面
                .defaultSuccessUrl("/LoginSuccess");

        // .logoutSuccessUrl("/"); 注销成功来到首页
        http.logout().logoutSuccessUrl("/toLogin");
        // 防止网站工具：get，post
        http.csrf().disable();//关闭csrf功能，登录失败肯定存在的原因
        //开启记住我功能: cookie,默认保存两周,自定义接收前端的参数
        http.rememberMe()
                .userDetailsService(userDetailsService)
                .tokenRepository(persistentTokenRepository)
                .tokenValiditySeconds(86400);
        //没有权限时拒绝访问页面，即进行页面拦截 返回到指定的页面 URL路径
        http.exceptionHandling().accessDeniedPage("/unauth");
        //关闭窗口拦截，失效
        http.headers().frameOptions().disable();
        //拦截路径以及角色访问
        http.authorizeRequests()
                .antMatchers("/","/index").permitAll()
                //查询权限
                .antMatchers("/tobillselectOne","/admin/selectOne",
                        "/code/selectOne","/email/selectOne",
                        "/selectSupplierOne","/toUserselectOne"
                ).hasAuthority("vip1")
                //修改权限
                .antMatchers("/toadminupdate/{acco_id}","/tobillupdate/{goods_name}",
                        "/tocodeupdate/{acco_name}","/toemailupdate/{email_add}",
                        "/tosupplierupdate/{supplier_name}","/touserupdate/{user_name}"
                ).hasAuthority("vip2")
                //新增权限
                .antMatchers("/articleadd","/toaddpage",
                        "/toemailaddpage","/supplierinsert",
                        "/memberadd"
                ).hasAuthority("vip3")
                //删除权限
                .antMatchers("/tobilldelete/{bill_id}","/tocodedelete/{acco_id}",
                        "/toemaildelete/{email_id}","/tosupplierdelete/{supplier_id}",
                        "/touserdelete/{user_id}"
                ).hasAuthority("vip4");

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //认证
        //Spring security 5.0中新增了多种加密方式，也改变了密码的格式。
        //要想我们的项目还能够正常登陆，需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
        //spring security 官方推荐的是使用bcrypt加密方式。
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).authorities("vip1");
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }




    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }

}
